Tamaño y resolución en gráficos

Christian Ballejo

Gráficos que no hacen lo que quiero


Muchas veces nos encontramos con la situación de crear un gráfico que se ve bien en el panel Plot de RStudio y cuando lo exportamos o incluímos dentro de un documento de Quarto el tamaño de sus partes (elementos geométricos, textos, leyendas, etc) se achican o agrandan de tal forma que el producto final es feo y/o desproporcionado.


La respuesta a estos problemas tienen que ver con dos conceptos que debemos entender y poder controlar: el tamaño y la resolución.

Pantalla


Repasemos algunos conceptos de la imagen en pantalla:

  • La pantalla es una matriz de pixeles. Todas las imagenes que vemos en ella estan compuesta por ellos.
  • La que estoy utilizando ahora, para hacer esta presentación, tiene una dimensión de 24 pulgadas con un ratio de aspecto 16/10 (20 x 12,5 pulgadas)
  • La resolución es de 1920 x 1200, es decir tiene 1920 píxeles de ancho y 1200 píxeles de alto.
  • El número de píxeles por pulgada es de 96 (dpi).

Pantalla


Hagamos algunos calculos para ver si todo está en orden:


  • ancho: 1920 (px) / 96 (px/in) = 20 pulgadas

  • alto: 1200 (px) / 96 (px/in) = 12,5 pulgadas

  • relación: 1920 / 1200 = 20 / 12,5 = 16/10

Archivos de imagen


Las imágenes que se crean con ggplot2, por ejemplo, están constituidas por pixeles.

En estas imágenes también se relacionan las dimensiones y las resoluciones.

Para pasar de la dimensión en pulgadas a una cantidad de puntos, por ejemplo al exportar con ggsave() se utiliza la cantidad de puntos por pulgadas (dpi).

Si creamos un gráfico de 12 x 10 pulgadas a 300 dpi, el archivo será una matriz de (12 * 300) x (10 * 300) = 3600 x 3000 puntos.

Cuando abrimos el archivo en nuestra computadora, cada punto representa un pixel, lo que da una imagen de 3600 x 3000 px de resolución.

Experimento práctico


Hagamos un pequeño experimento con un gráfico sencillo basado en los pinguinos.

library(tidyverse)
library(datos)

pinguinos |>
    ggplot(aes(largo_pico_mm, 
               alto_pico_mm, 
               color = especie)) +
    geom_point()

Experimento práctico


ggsave("prueba.png", 
       width = 10, 
       height = 5, 
       dpi = 300)

Si calculamos, la salida se almacena como:

  • ancho: 10 pulgadas * 300 dpi = 3000 px

  • alto: 5 pulgadas * 300 dpi = 1500 px

Ahora si en lugar de guardar el gráfico solo lo visualizaramos en el monitor:

  • ancho: 10 pulgadas * 96 dpi = 960 px

  • alto: 5 pulgadas * 96 dpi = 480 px

Experimento práctico


  • La relación entre el tamaño de la pantalla y el tamaño físico depende del dpi (puntos por pulgada) del dispositivo gráfico, que es 96 por defecto para la pantalla.
  • Luego, si guardamos el gráfico con un dpi mayor o menor, el archivo se guarda como una matriz de puntos usando el nuevo dpi y el tamaño en pulgadas.
  • Entonces, cuando se abre en la computadora, la dimensión del tamaño en píxeles es diferente.

Si visualizamos un gráfico con muchos más pixeles que otro en el mismo espacio (nuestra pantalla) los elementos que lo componen se van a ver siempre más pequeños.

¿Por qué es importante esta diferencia?




Importa porque algunos elementos del gráfico se ajustan al espacio disponible, y algunos son fijos y medidos en su dimensión real (cm, mm o pulgadas) como las fuentes de los textos, creando una distorsión al cambiar la dimensión del gráfico o su resolución.

Tamaño predeterminado en Quarto

Formato Por defecto
Por defecto 7 x 5
Diapositivas HTML 9,5 x 6,5
Diapositivas HTML (reveal.js) 9 x 5
PDF 5,5 x 3,5
Diapositivas PDF (Beamer) 10x7
PowerPoint 7,5 x 5,5
MS Word, ODT, RTF 5x4
EPUB 5x4

* Medidas en pulgadas

Grafico con tamaño predeterminado (9 x 5”)

Grafico con tamaño al 50% (4.5 x 2.5”)

Grafico con tamaño 12 x 6.67”

Archivos exportados


Comparemos dos archivos exportados desde ggplot2:

font_prueba1_5x5_300.png

font_prueba1_10x10_300.png

Problemas con fuentes


Observamos que el tamaño del punto y la fuente parecen más pequeños en el gráfico de la derecha.

De hecho no son más pequeños, siguen teniendo el mismo tamaño en pulgadas, y como guardamos con la misma resolución (dpi = 300), tienen el mismo número de puntos (tamaño en pulgadas * 300).

La fuente del gráfico aparece más pequeña porque el segundo gráfico es más grande (3000x3000 frente a 1500x1500) y se reduce su aspecto para que el gráfico entre el espacio de la pantalla.

Que hacemos


Hay 3 soluciones posibles:

  • Ajustar el tamaño de las fuentes, lineas, etc. cuando cambie el tamaño o la resolución del gráfico, pero si el gráfico es complejo, eso podría implicar muchas modificaciones.


  • Establecer el tamaño del gráfico en pulgadas y la resolución al principio, y luego trabajar en la personalización.


  • Para exportar gráficos, utilizar un paquete como ragg que tiene un parámetro de escala para manejar los cambios de dimensión manteniendo las proporciones.

Diferencia en tamaño de fuentes


Además tenemos otro problema. De forma predeterminada, el tamaño de las fuentes de la configuración de theme() está definido en pts. (15 significa 15 puntos - pts-).

En cambio, en la capa geom_text(), el tamaño se define en mm, por lo que 15 es 15 mm.


¿Cuál es la relación entre pts y mm o in?


1 punto = 1/72 pulgadas


1 punto = 0,35 mm

Diferencia en tamaño de fuentes


Entonces si queremos que el texto tenga el mismo tamaño que el título, el tamaño en mm será 15 pt * 0,35 pt/mm = 5,25 mm

En ggplot, hay una constante definida para realizar la conversión, .pt = 2,845276. (1/.pt = 0,35). Podemos escribir .pt en la consola y mostrará su valor:

.pt
[1] 2.845276
1/.pt
[1] 0.3514598

Entonces para hacer la conversión:

de pt a mm : mm = pt / .pt -> 15 / 2,845276 = 5,27 mm

de mm a pt : pt = mm * .pt -> 5,27 * 2,845276 = 15 pts

Diferencia en tamaño de fuentes


pinguinos |>
    ggplot(aes(x = largo_pico_mm, 
               y = alto_pico_mm, 
               color = especie)) +
  geom_point() +
  geom_text(x = 45, 
            y = 20, 
            label = "Ejemplo font 15", 
            size = 15, 
            inherit.aes = FALSE) +
  labs(title = "Relación entre largo y altura de picos por especies") +
  theme(plot.title = element_text(size = 15))

Diferencia en tamaño de fuentes

pinguinos |>
    ggplot(aes(x = largo_pico_mm, 
               y = alto_pico_mm, 
               color = especie)) +
  geom_point()+
  geom_text(x = 45, 
            y = 20, 
            label = "Ejemplo font 15", 
            size = 15/.pt, 
            inherit.aes = FALSE) +
  labs(title = "Relación entre largo y altura de picos por especies") +
  theme(plot.title = element_text(size = 15))

Paquete ragg


Este paquete declara un espacio de exportación con agg_*() (por ejemplo para un archivo png), luego se ejecuta el código del gráfico, finalmente se cierra el espacio con dev.off().


La función incorpora un argumento scaling que posibilita escalar los elementos como el texto adaptandose a variaciones en los tamaños de salida.

Paquete ragg


PNG de 10 x 10 pulgadas con resolucion de 300 dpi

ragg::agg_png("ragg_10x10.png", 
              width = 10, 
              height = 10, 
              units = "in", 
              res = 300)


PNG de 20 x 20 pulgadas con resolucion de 300 dpi

ragg::agg_png("ragg_20x20.png", 
              width = 20, 
              height = 20, 
              units = "in", 
              res = 300,
              scaling = 2)